# coding=utf-8
import hashlib
import json
import sys
import time
import urllib.request
import urllib.parse
from importlib import reload

import requests

reload(sys)

FATEA_PRED_URL = "http://pred.fateadm.com"


def LOG(log):
    # 不需要测试时，注释掉日志就可以了
    print(log)
    log = None


class TmpObj:
    def __init__(self):
        self.init = True
        self.value = None


class Rsp:
    def __init__(self):
        self.ret_code = -1
        self.cust_val = 0.0
        self.err_msg = "succ"
        self.pred_rsp = TmpObj()

    def ParseJsonRsp(self, rsp_data):
        if rsp_data is None:
            self.err_msg = "http request failed, get rsp Nil data"
            return
        jrsp = json.loads(rsp_data)
        self.ret_code = int(jrsp["RetCode"])
        self.err_msg = jrsp["ErrMsg"]
        self.request_id = jrsp["RequestId"]
        if self.ret_code == 0:
            rslt_data = jrsp["RspData"]
            if rslt_data is not None and rslt_data != "":
                jrsp_ext = json.loads(rslt_data)
                if "cust_val" in jrsp_ext:
                    data = jrsp_ext["cust_val"]
                    self.cust_val = float(data)
                if "result" in jrsp_ext:
                    data = jrsp_ext["result"]
                    self.pred_rsp.value = data


def CalcSign(pd_id, passwd, timestamp):
    md5 = hashlib.md5()
    md5.update((timestamp + passwd).encode("utf8"))
    csign = md5.hexdigest()

    md5 = hashlib.md5()
    md5.update((pd_id + timestamp + csign).encode("utf8"))
    csign = md5.hexdigest()
    return csign


def CalcCardSign(cardid, cardkey, timestamp, passwd):
    md5 = hashlib.md5()
    md5.update(passwd + timestamp + cardid + cardkey)
    return md5.hexdigest()


def HttpRequest(url, body_data):
    rsp = Rsp()
    post_data = urllib.parse.urlencode(body_data).encode("utf8")
    request = urllib.request.Request(url, post_data)
    request.add_header("User-Agent", "Mozilla/5.0")
    rsp_data = urllib.request.urlopen(request).read()
    rsp.ParseJsonRsp(rsp_data)
    return rsp


def PostFile(url, data, img_data):
    rsp = Rsp()
    files = {'img_data': ('img_data', img_data)}
    headers = {"User-Agent": "Mozilla/5.0"}
    r = requests.post(url, data=data, files=files, headers=headers)
    rsp.ParseJsonRsp(r.text)
    return rsp


class FateadmApi:
    # API接口调用类
    # 参数（appID，appKey，pdID，pdKey）
    def __init__(self, app_id, app_key, pd_id, pd_key):
        self.app_id = app_id
        if app_id is None:
            self.app_id = ""
        self.app_key = app_key
        self.pd_id = pd_id
        self.pd_key = pd_key
        self.host = FATEA_PRED_URL

    def SetHost(self, url):
        self.host = url

    #
    # 查询余额
    # 参数：无
    # 返回值：
    #   rsp.ret_code：正常返回0
    #   rsp.cust_val：用户余额
    #   rsp.err_msg：异常时返回异常详情
    #
    def QueryBalc(self):
        tm = str(int(time.time()))
        sign = CalcSign(self.pd_id, self.pd_key, tm)
        param = {
            "user_id": self.pd_id,
            "timestamp": tm,
            "sign": sign
        }
        url = self.host + "/api/custval"
        rsp = HttpRequest(url, param)
        if rsp.ret_code != 0:
            LOG("query failed ret: {} err: {}".format(rsp.ret_code, rsp.err_msg))
        return rsp

    #
    # 查询网络延迟
    # 参数：pred_type:识别类型
    # 返回值：
    #   rsp.ret_code：正常返回0
    #   rsp.request_id：唯一的订单号
    #   rsp.err_msg： 异常时返回异常详情
    #
    def QueryTTS(self, pred_type):
        tm = str(int(time.time()))
        sign = CalcSign(self.pd_id, self.pd_key, tm)
        param = {
            "user_id": self.pd_id,
            "timestamp": tm,
            "sign": sign,
            "predict_type": pred_type,
        }
        if self.app_id != "":
            #
            asign = CalcSign(self.app_id, self.app_key, tm)
            param["appid"] = self.app_id
            param["asign"] = asign
        url = self.host + "/api/qcrtt"
        rsp = HttpRequest(url, param)
        if rsp.ret_code == 0:
            LOG("query rtt succ ret: {} request_id: {} err: {}".format(rsp.ret_code, rsp.request_id, rsp.err_msg))
        else:
            LOG("predict failed ret: {} err: {}".format(rsp.ret_code, rsp.err_msg))
        return rsp

    #
    # 识别验证码
    # 参数：pred_type:识别类型  img_data:图片的数据
    # 返回值：
    #   rsp.ret_code：正常返回0
    #   rsp.request_id：唯一订单号
    #   rsp.pred_rsp.value：识别结果
    #   rsp.err_msg：异常时返回异常详情
    #
    def Predict(self, pred_type, img_data):
        tm = str(int(time.time()))
        sign = CalcSign(self.pd_id, self.pd_key, tm)
        param = {
            "user_id": self.pd_id,
            "timestamp": tm,
            "sign": sign,
            "predict_type": pred_type,
            "up_type": "mt"
        }
        if self.app_id != "":
            #
            asign = CalcSign(self.app_id, self.app_key, tm)
            param["appid"] = self.app_id
            param["asign"] = asign
        url = self.host + "/api/capreg"
        files = img_data
        rsp = PostFile(url, param, files)
        if rsp.ret_code != 0:
            LOG("predict failed ret: {} err: {}".format(rsp.ret_code, rsp.err_msg))
            if rsp.ret_code == 4003:
                # lack of money
                LOG("cust_val <= 0 lack of money, please charge immediately")
        return rsp

    #
    # 从文件进行验证码识别
    # 参数：pred_type;识别类型  file_name:文件名
    # 返回值：
    #   rsp.ret_code：正常返回0
    #   rsp.request_id：唯一订单号
    #   rsp.pred_rsp.value：识别结果
    #   rsp.err_msg：异常时返回异常详情
    #
    def PredictFromFile(self, pred_type, file_name):
        with open(file_name, "rb") as f:
            data = f.read()
        return self.Predict(pred_type, data)

    #
    # 识别失败，进行退款请求
    # 参数：request_id：需要退款的订单号
    # 返回值：
    #   rsp.ret_code：正常返回0
    #   rsp.err_msg：异常时返回异常详情
    #
    # 注意:
    #    Predict识别接口，仅在ret_code == 0时才会进行扣款，才需要进行退款请求，否则无需进行退款操作
    # 注意2:
    #   退款仅在正常识别出结果后，无法通过网站验证的情况，请勿非法或者滥用，否则可能进行封号处理
    #
    def Justice(self, request_id):
        if request_id == "":
            #
            return
        tm = str(int(time.time()))
        sign = CalcSign(self.pd_id, self.pd_key, tm)
        param = {
            "user_id": self.pd_id,
            "timestamp": tm,
            "sign": sign,
            "request_id": request_id
        }
        url = self.host + "/api/capjust"
        rsp = HttpRequest(url, param)
        if rsp.ret_code == 0:
            LOG("justice succ ret: {} request_id: {} pred: {} err: {}".format(rsp.ret_code, rsp.request_id,
                                                                              rsp.pred_rsp.value, rsp.err_msg))
        else:
            LOG("justice failed ret: {} err: {}".format(rsp.ret_code, rsp.err_msg.encode('utf-8')))
        return rsp

    #
    # 充值接口
    # 参数：cardid：充值卡号  cardkey：充值卡签名串
    # 返回值：
    #   rsp.ret_code：正常返回0
    #   rsp.err_msg：异常时返回异常详情
    #
    def Charge(self, cardid, cardkey):
        tm = str(int(time.time()))
        sign = CalcSign(self.pd_id, self.pd_key, tm)
        csign = CalcCardSign(cardid, cardkey, tm, self.pd_key)
        param = {
            "user_id": self.pd_id,
            "timestamp": tm,
            "sign": sign,
            'cardid': cardid,
            'csign': csign
        }
        url = self.host + "/api/charge"
        rsp = HttpRequest(url, param)
        if rsp.ret_code == 0:
            LOG("charge succ ret: {} request_id: {} pred: {} err: {}".format(rsp.ret_code, rsp.request_id,
                                                                             rsp.pred_rsp.value, rsp.err_msg))
        else:
            LOG("charge failed ret: {} err: {}".format(rsp.ret_code, rsp.err_msg.encode('utf-8')))
        return rsp

    ##
    # 充值，只返回是否成功
    # 参数：cardid：充值卡号  cardkey：充值卡签名串
    # 返回值： 充值成功时返回0
    ##
    def ChargeExtend(self, cardid, cardkey):
        return self.Charge(cardid, cardkey).ret_code

    ##
    # 调用退款，只返回是否成功
    # 参数： request_id：需要退款的订单号
    # 返回值： 退款成功时返回0
    #
    # 注意:
    #    Predict识别接口，仅在ret_code == 0时才会进行扣款，才需要进行退款请求，否则无需进行退款操作
    # 注意2:
    #   退款仅在正常识别出结果后，无法通过网站验证的情况，请勿非法或者滥用，否则可能进行封号处理
    ##
    def JusticeExtend(self, request_id):
        return self.Justice(request_id).ret_code

    ##
    # 查询余额，只返回余额
    # 参数：无
    # 返回值：rsp.cust_val：余额
    ##
    def QueryBalcExtend(self):
        rsp = self.QueryBalc()
        return rsp.cust_val

    ##
    # 从文件识别验证码，只返回识别结果
    # 参数：pred_type;识别类型  file_name:文件名
    # 返回值： rsp.pred_rsp.value：识别的结果
    ##
    def PredictFromFileExtend(self, pred_type, file_name):
        rsp = self.PredictFromFile(pred_type, file_name)
        return rsp.pred_rsp.value

    ##
    # 识别接口，只返回识别结果
    # 参数：pred_type:识别类型  img_data:图片的数据
    # 返回值： rsp.pred_rsp.value：识别的结果
    ##
    def PredictExtend(self, pred_type, img_data):
        rsp = self.Predict(pred_type, img_data)
        return rsp.pred_rsp.value


def TestFunc():
    # pd账号秘钥，请在用户中心页获取
    pd_id = "2"
    pd_key = "2"
    app_id = "2"
    app_key = "2+aqJbCProjHcGofDu"
    # 具体类型可以查看官方网站的价格页选择具体的类型，不清楚类型的，可以咨询客服
    pred_type = "30400"
    # 初始化api接口
    api = FateadmApi(app_id, app_key, pd_id, pd_key)
    # 查询余额接口
    balance = api.QueryBalcExtend()  # 直接返余额
    # api.QueryBalc()

    # 通过文件识别验证码
    # 通过文件进行验证码识别,请使用自己的图片文件替换
    # 如果是通过url直接获取内存图片，这直接调用 Predict 接口就好
    # file_name = "img.jpg"
    # res =  api.PredictFromFileExtend(pred_type,file_name)  	# 直接返回识别结果
    # 多网站类型时，需要增加src_url参数，具体请参考api文档: http://docs.fateadm.com/web/#/1?page_id=6
    # rsp = api.PredictFromFile(pred_type, file_name)  # 返回识别结果的详细信息

    # 如果不是通过文件识别，则调用Predict接口：
    # res = api.PredictExtend(pred_type, "http://search.neea.edu.cn/Imgs.do?act=verify&t=4324234234234")  # 直接返回识别结果
    rsp = api.Predict(pred_type,
                      b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x02\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\t\t\x08\n\x0c\x14\r\x0c\x0b\x0b\x0c\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\x1d\x1a\x1c\x1c $.\' ",#\x1c\x1c(7),01444\x1f\'9=82<.342\xff\xdb\x00C\x01\t\t\t\x0c\x0b\x0c\x18\r\r\x182!\x1c!22222222222222222222222222222222222222222222222222\xff\xc0\x00\x11\x08\x00d\x00\xb4\x03\x01"\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\xff\xc4\x00\xb5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01}\x01\x02\x03\x00\x04\x11\x05\x12!1A\x06\x13Qa\x07"q\x142\x81\x91\xa1\x08#B\xb1\xc1\x15R\xd1\xf0$3br\x82\t\n\x16\x17\x18\x19\x1a%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xc4\x00\x1f\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\xff\xc4\x00\xb5\x11\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02w\x00\x01\x02\x03\x11\x04\x05!1\x06\x12AQ\x07aq\x13"2\x81\x08\x14B\x91\xa1\xb1\xc1\t#3R\xf0\x15br\xd1\n\x16$4\xe1%\xf1\x17\x18\x19\x1a&\'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00r\x8a\x91E5EJ\xa2\x80\x1c\xa2\xa4QMQR(\xa0\x07(\xa9TSTT\x8a(\x01\xca*E\x14\xd5\x15*\x8a\x00r\x8a\x91E5EJ\xa2\x80\x15EJ\xa2\x9a\xa2\xa4Q@\x0eQR(\xa4QR(\xa0\x07\x01R(\xa6\xa8\xa9\x14P\x03\x94T\x8a)\xaa*U\x14\x00\xe5\x15"\x8aj\x8a\x91E\x009EJ\xa2\x9a\xa2\xa4Q@\n\x07\x14S\xc0\xa2\x80<\x8dEH\xa2\x9a\xa2\xa5Q@\x0eQR(\xa6\xa8\xa9\x14P\x03\x94T\xaa)\xaa*E\x14\x00\xe5\x15"\x8aj\x8a\x95E\x009EH\xa2\x9a\xa2\xa4Q@\x0eQR\xa8\xa6\xa8\xa9\x14P\x03\x94T\x80STT\x8a(\x01\xca*U\x14\xd5\x15"\x8a\x00r\x8am\xc5\xd4\x16q\xab\xdcH#F`\xa0\x9e\x99\xa9\x14V/\x8b\x17:B\x1fI\x81\xfd\r\x00oC,s\xa0x\xa4I\x10\xf4d \x8a\x9dEyL.\xd1L\x8e\xacT\x829\x07\x15\xeb\n(\x01\xca*U\x14\xd5\x15"\x8a\x00P8\xa2\x9e\x07\x14P\x07\x91\xa8\xa9\x14STS\x9d\xc4hX\xfe\x02\x80$QR\x0c\x01\x93\xc0\x15\x98\xd7\x12\x13\xc3\x10*=\xa6F\xce\xdd\xcc=\x074\x01\xb2\x92\xc6zH\xa7\xf1\xa9\xd4V\x03+!\xf9\x81\x06\xb4t\xfb\xb2\xcc!~\x7f\xbah\x03ME?!FI\x00z\x9a\x82i\xd6\xde=\xcd\xd4\xf4\x15\x8fs}-\xc1#q\t\xe8\r\x00j\xcd\xab[@v\xaeea\xfd\xce\x9f\x9d>\rb\xdaF\xc3nA\xd8\xb0\xac{k\t\xee\x86\xe8\xd7\x0b\x9c\x12\xdcT\xd2h\xf7q\xa9`\xaa\xc0\x0c\xfc\xa6\x80:]\xca\xa9\xbc\x91\xb7\xd6\x9b-\xed\xbc\x08\xec\xd2+\x14\x19dR\x0b~U\x89\xa6\\K,\x176N\xa4\x90\x8cW\x03\x9c\xf7\xfeb\xb1\x8a\xf5\r\xd4\x1c\x1es\xcd\x00v\xab\xa8\xdb\x9bO\xb4\xe4\xacy\xc0\xdc0MQ\x1e&\x84K\x83\x03\xec\xf5\xcf\xd3\xff\x00\xaf\xfaV\x0c~m\xc2\xc5l\x9c\x8c\xf0\x00\x1d\xfe\x95%\xe6\x9b-\x90S+ \xdc2\x06y\xfc\xa8\x03\xb6\xb5\xb9\x86\xee?2\x17\xdc\xb9\xc6j\xc9*\x8aY\x98*\x8e\xa4\x9c\x01^{e{%\x95\xc2\xca\x9c\xed?t\x9e\x0f\xf9\xc9\xad\x1b\xfdb\xf2\xfdR\xd5UWv2\xb1\x92KP\x06\xc5\xd7\x8am\xad\xe5\xf2\xe2\x85\xa6\xc1\xc1m\xc0\x0f\xc3\xad3S\xd4\xadu_\x0e\xdc\xb4Y\x12FP\x94=G\xcc\x06~\x9c\x9a\xc1\xb9\xd0\xef\xad-\x05\xc4\xb1\x80\xbd\xc09#\xebY\xe0\xe2\x80\x12\xbdA5m<\xc4\x925\xed\xbanP\xd8iW"\xbc\xbe\xb7\xaf\xaf\xed\x13A\xb3\x86\xde\xd6\x05\xb8\x92?\xdeH\x10n\xe3\x8e\xbe\xa7\x14\x01\xd4M\xe2\xcd&\t\x02\t^_S\x1a\xe4\x0f\xc4\xe3\xf4\xad\x8b\x1b\xdbk\xf8|\xdbiD\x89\xd0\xe3\xb5yCY]$"f\xb7\x95b=\x1c\xa1\x00\xd5\x9d\x1fV\x9bH\xbeY\xe3$\xa1\xe2D\xcf\x0c(\x03\xd6\x80\xa2\x99iq\x1d\xe5\xacw\x10\xb6\xe8\xe4\\\x83E\x00yB\x8a\x8e\xeb"!\xe8MN\xa2\xa3\xbb\x8b| \xff\x00p\xee\xfd\x08\xfe\xb4\x01B\xb6-\xa2X\xa2\x04\x80\x0e2Mc\xd2m\x0f&\x00\xdc\xfdp\x06M\x00i\xde\\\xdb\xc9\tE}\xed\xd4m\xe4~}+=\x1c\xa3\xab\x8e\xa0\xe6\xa7\x8bO\xb9\x94d A\xd8\xb9\xc6\x7f\xadJt\x9b\x9cd\x18\x8f\x1d7\x1c\xff\x00*\x005\t\x8c\xa2.\xc0\xa88\xcdS\x8d\x0c\x92\x04PI=\x00\xa9\xeem\xe4\x82\x1b\x7f4a\xf6\x90W9\xc7\xccH\xfeu\x04|\xc8\xbf\xbc1\xf3\xf7\x87j\x00\xeb\xe2\x8cF\x8a\x8b\xd1F\x05N\xa2\xa9I\xa8[A\x12\xbc\x8f\xcb\x0c\x84\x1c\xb7\xe5M\x8a{\xeb\xc4\xccP\xad\xba\x1f\xe3\x93\x93\xf8\n\x00\xbb,Qm.\xed\xb3\x1dX6\xdc\x8ex\'\xd3\x9a\xe2\xe4P\x93:\x87\xde\xa0\xf0k\xafM.&`\xf7.\xf7/\xff\x00M\x0f\x03\xe8:W5\xaa\xc2\xb6\xfa\x9c\xb1\xaa\x85\xe8p\x0f\x1c\xd0\x04\xfa-\xb9\x9e\xec(\x96H\xf3\xc11\xf0q\x83\x9e\x7f/\xccWU\x06\x97g\n\x90\xb0\x86f\xfb\xce\xff\x003\x1f\xc4\xd7-\xe1\xfd\xbf\xda\xc8\t \xb7A\x9e\t\x1e\xb5\xdb\x00H88=\x8d\x00y\xbb\xae\xd7e\x07 \x1e\x0f\xaf\xbdt~\x14\xb1Ye{\xb7\nB\x1d\xa3=CpsXW\xd1\xacW\xb2\xa2}\xc0p\xa4w\x03\x8e9<q\xc7=1[\xde\x0e\x0cnn0\xd8P\x9f2\xe7\xa9$`\xfe\x18?\x9d\x00t\xf7\xb05\xcd\x8c\xd0\xa67:\x103\xeb^e^\xb0\x05y]\xc2yW2\xc7\x826\xb9\\\x1e\xd84\x01\x1dt~\x13\xd2\x06\xa1vn\']\xd0A\x80\x14\xf2\x0bu\xc5s\x95\xd9\xf8\t\xf3\xf6\xe8\xc9\xfe\xe3\x01\xff\x00}g\xfaP\x07bbI"1\xb2\x02\x84`\xa9\x1cb\xbc\xa7X\xb2\x1av\xadqh\x0eDl1\xf4 \x11\xfc\xeb\xd6\xd4W\x9bx\xcfg\xfc$r\xed\xc6v.\xfcz\xe3\xfc1@\x0c\xd2|Ks\xa6Y\x0bes\xb01*1\xd3?\xfd|\xd1XTP\x06\xaa\x8a\x93he*z\x11\x8aE\x15"\x8a\x00\xc6\x963\x14\x85Oj\x9e\xda\xf5\xe0\x18?2\xff\x00t\xff\x00J\x92h\xcd\xd5\xebF06\xaf\x1e\xff\x00\xe75]\xad\'V\xc7\x96\xc7\xe8:\xd0\x06\x8bj\xb0\xaa\x82\x88\xcc}\x0f\x18\xa4\x1a\xc2\x83\xfe\xa8\xe3\xebY\xaf\x03\xc6\xb9\x90\x05\xf4\x04\xf2\x7f\x0e\xb4\xe8`7\x12\xacq\x03\x93\xdd\xbaP\x06\x85\xe5\xcc\x17\x96%\xc1\n\xe8\xd8\xc3u\'\xdb\xf3\xac\x9a\xe8l\xb4\x98\xa0\xf9\xa6\x0b#\xe7\x8e8\x1f\x85Eu\xa2\x16b\xf6\xe4r~\xe9\xa0\x0c\xdbK\xa5\xb5\x93\xcc\xf2\x83\xbf\xabv\xad\xb8u\xfbr\xc1eF\\\x91\x829\x03\xebT\x17@\xba`2\xc8\x0eq\xc9\xe9\xefH|?z\xb8?#q\x93\x83\xfaP\x06\xef\xf6\xb5\xa0 o\xeav\xfas\xfc\xeb\x0f\xc4i\xb7U\xcf\xf7\xa3\x1f\xd6\x8b]\x1e\xec^\xc5\xe6#\x04W\x04\x90\x0e?\xa5^\xd74\xeb\xbb\xddE\r\xbc%\xd4F\x01l\x80:\x9fZ\x00\xcc\xd0Wv\xb7n>\xa7\xf45\xde(\xaeoI\xd0.l\xef\xe3\x9ec\x19\t\x9f\xba\xe7\xb8\xf4\xc7\xf5\xae\x9dE\x00p:\xf2\xed\xd6\xae=\xcf\xf7\xf7\x7f\xfa\xbe\x95w\xc2<\xea\xec0\xc7\xf7d\x8ct\x1e\xe7\xfc\xf7\xa4\xf1\x06\x99z\xfa\xa4\x93%\xbb\xbcn@VE\xceN=\x05Z\xf0\x9d\x8d\xccZ\x8bO-\xbc\x89\x1f\x97\xc36@\xeb\xfa\xd0\x07d\xa2\xbc\xc7WR\xba\xc5\xe08\xcf\x9c\xe7\x8f\xadz\x8a\x8a\xe5\xf5?\x07Iwu5\xcd\xbd\xda\x07\x91\xcbyr.\x00\xcf\xb8\xff\x00\n\x00\xe2\xabg\xc3\xba\xcah\xb7rK$l\xeb"\xed!ONj;\x9f\r\xea\xf6\xcd\x86\xb2\x91\xc7c\x10\xdf\x9f\xca\xb4\xf4_\x08M\x7f\x04\xcfx\xb2\xda\xb0  t\xc1>\xf84\x01\xa7s\xe3\xc8\x16"-m\\\xc9\x8e\xaf\x8c\x03\xfdk\x8a\xba\xba\x96\xf2\xe6K\x89\x9b.\xe7$\xd7V~\x1f\xdd\x13\xf2\xdeC\x8fpj\xc4\x1f\x0f\t`g\xbd\x18\xcf!\x16\x808\xb8\xed\xe6\x95wG\x1b0\xce2\x05\x15\xec6\x1a\x1d\x8d\x85\xaa\xc1\x14\n@\xe4\x96\x19$\xd1@\x1ef\xa2\xa4QH\xa2\xa4Q@\x19kp\x90_M!\x05\x87 c\xebS\x87\xbe\xbc\xe25\xf2\xa3=\xfa~\xb4\x961\xa3\xdfNJ\x83\xb4\x9cdt\xe6\xb5\xd4P\x05+}*\x14;\xa5&F\xf7\xe9W!\xb3\x86\x19\x9aX\xd0+0\xc1\xc7J\x95EH\xa2\x80\x1c\xa2\xa5QMQR(\xa0\x07(\xa9\x14S@\xa9\x14P\x03\x94T\x8a)\x14T\x8a(\x01\xca*E\x14\xd5\x15*\x8a\x00U\x15*\x8aj\x8a\x91E\x009EJ\xa2\x9a\xa2\xa4Q@\x0eQR(\xa6\xa8\xa9TP\x03\x94T\x8a)\xaa*E\x14\x00\xe08\xa2\x9c\x05\x14\x01\xe4kR-\x14P\x02Co\x1c.\xec\x80\x82\xddy\xabKE\x14\x01"\xd4\x8bE\x14\x01*\xd4\x8bE\x14\x01"\xd4\x8bE\x14\x01*\xd4\x8bE\x14\x01"\xd4\xabE\x14\x01"\xd4\x8bE\x14\x01*\xd4\x8bE\x14\x01"\xd4\xabE\x14\x01"\xd4\x8bE\x14\x01 \x1cQE\x14\x01\xff\xd9')  # 返回识别结果的详细信息
    print(rsp.__dict__)
    print(rsp.pred_rsp.__dict__)

    just_flag = False
    if just_flag:
        if rsp.ret_code == 0:
            # 识别的结果如果与预期不符，可以调用这个接口将预期不符的订单退款
            # 退款仅在正常识别出结果后，无法通过网站验证的情况，请勿非法或者滥用，否则可能进行封号处理
            api.Justice(rsp.request_id)


if __name__ == "__main__":
    TestFunc()
